// HTTP请求工具
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useUserStore } from '@/stores/modules/user'
import type { ApiResponse } from '@/types'

// 请求配置接口
interface RequestConfig extends AxiosRequestConfig {
  showLoading?: boolean
  showError?: boolean
  showSuccess?: boolean
  successMessage?: string
}

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// 请求拦截器
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    const userStore = useUserStore()
    
    // 添加认证token
    if (userStore.token) {
      config.headers = {
        ...config.headers,
        Authorization: `Bearer ${userStore.token}`
      }
    }
    
    // 添加请求ID用于追踪
    config.headers = {
      ...config.headers,
      'X-Request-ID': generateRequestId()
    }
    
    // 显示加载状态
    const customConfig = config as RequestConfig
    if (customConfig.showLoading !== false) {
      // 这里可以显示全局loading
      console.log('Request started:', config.url)
    }
    
    return config
  },
  (error: AxiosError) => {
    console.error('Request error:', error)
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    const customConfig = response.config as RequestConfig
    
    // 隐藏加载状态
    if (customConfig.showLoading !== false) {
      console.log('Request completed:', response.config.url)
    }
    
    const { data } = response
    
    // 处理业务错误
    if (data.code !== 200) {
      const errorMessage = data.message || '请求失败'
      
      // 显示错误信息
      if (customConfig.showError !== false) {
        ElMessage.error(errorMessage)
      }
      
      // 处理特殊错误码
      switch (data.code) {
        case 401:
          // 未授权，跳转到登录页
          handleUnauthorized()
          break
        case 403:
          // 无权限
          ElMessage.error('无权限访问')
          break
        case 404:
          // 资源不存在
          ElMessage.error('请求的资源不存在')
          break
        case 500:
          // 服务器错误
          ElMessage.error('服务器内部错误')
          break
      }
      
      return Promise.reject(new Error(errorMessage))
    }
    
    // 显示成功信息
    if (customConfig.showSuccess && customConfig.successMessage) {
      ElMessage.success(customConfig.successMessage)
    }
    
    return data
  },
  (error: AxiosError) => {
    const customConfig = error.config as RequestConfig
    
    // 隐藏加载状态
    if (customConfig?.showLoading !== false) {
      console.log('Request failed:', error.config?.url)
    }
    
    let errorMessage = '网络错误'
    
    if (error.response) {
      // 服务器响应了错误状态码
      const { status, data } = error.response
      
      switch (status) {
        case 400:
          errorMessage = '请求参数错误'
          break
        case 401:
          errorMessage = '未授权，请重新登录'
          handleUnauthorized()
          break
        case 403:
          errorMessage = '拒绝访问'
          break
        case 404:
          errorMessage = '请求地址不存在'
          break
        case 408:
          errorMessage = '请求超时'
          break
        case 500:
          errorMessage = '服务器内部错误'
          break
        case 501:
          errorMessage = '服务未实现'
          break
        case 502:
          errorMessage = '网关错误'
          break
        case 503:
          errorMessage = '服务不可用'
          break
        case 504:
          errorMessage = '网关超时'
          break
        case 505:
          errorMessage = 'HTTP版本不受支持'
          break
        default:
          errorMessage = (data as any)?.message || `连接错误${status}`
      }
    } else if (error.request) {
      // 请求已发出但没有收到响应
      errorMessage = '网络连接异常'
    } else {
      // 其他错误
      errorMessage = error.message || '请求失败'
    }
    
    // 显示错误信息
    if (customConfig?.showError !== false) {
      ElMessage.error(errorMessage)
    }
    
    return Promise.reject(error)
  }
)

// 处理未授权
function handleUnauthorized() {
  const userStore = useUserStore()
  
  ElMessageBox.confirm(
    '登录状态已过期，您可以继续留在该页面，或者重新登录',
    '系统提示',
    {
      confirmButtonText: '重新登录',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    userStore.logout()
    // 这里可以跳转到登录页
    window.location.reload()
  })
}

// 生成请求ID
function generateRequestId(): string {
  return Date.now().toString(36) + Math.random().toString(36).substr(2)
}

// 请求方法封装
class Request {
  /**
   * GET请求
   */
  static get<T = any>(
    url: string,
    params?: any,
    config?: RequestConfig
  ): Promise<ApiResponse<T>> {
    return service.get(url, {
      params,
      ...config
    })
  }
  
  /**
   * POST请求
   */
  static post<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<ApiResponse<T>> {
    return service.post(url, data, config)
  }
  
  /**
   * PUT请求
   */
  static put<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<ApiResponse<T>> {
    return service.put(url, data, config)
  }
  
  /**
   * DELETE请求
   */
  static delete<T = any>(
    url: string,
    config?: RequestConfig
  ): Promise<ApiResponse<T>> {
    return service.delete(url, config)
  }
  
  /**
   * PATCH请求
   */
  static patch<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<ApiResponse<T>> {
    return service.patch(url, data, config)
  }
  
  /**
   * 上传文件
   */
  static upload<T = any>(
    url: string,
    file: File | FormData,
    config?: RequestConfig & {
      onUploadProgress?: (progressEvent: any) => void
    }
  ): Promise<ApiResponse<T>> {
    const formData = file instanceof FormData ? file : new FormData()
    
    if (file instanceof File) {
      formData.append('file', file)
    }
    
    return service.post(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      ...config
    })
  }
  
  /**
   * 下载文件
   */
  static download(
    url: string,
    params?: any,
    filename?: string,
    config?: RequestConfig
  ): Promise<void> {
    return service.get(url, {
      params,
      responseType: 'blob',
      ...config
    }).then((response: any) => {
      const blob = new Blob([response.data])
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      
      link.href = downloadUrl
      link.download = filename || 'download'
      link.style.display = 'none'
      
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      
      window.URL.revokeObjectURL(downloadUrl)
    })
  }
  
  /**
   * 并发请求
   */
  static all<T = any>(requests: Promise<any>[]): Promise<T[]> {
    return Promise.all(requests)
  }
  
  /**
   * 请求重试
   */
  static retry<T = any>(
    requestFn: () => Promise<T>,
    maxRetries = 3,
    delay = 1000
  ): Promise<T> {
    return new Promise((resolve, reject) => {
      let retries = 0
      
      const attempt = () => {
        requestFn()
          .then(resolve)
          .catch((error) => {
            if (retries < maxRetries) {
              retries++
              setTimeout(attempt, delay * retries)
            } else {
              reject(error)
            }
          })
      }
      
      attempt()
    })
  }
}

// 请求缓存
class RequestCache {
  private static cache = new Map<string, { data: any; timestamp: number; ttl: number }>()
  
  /**
   * 生成缓存键
   */
  private static generateKey(url: string, params?: any): string {
    return `${url}?${JSON.stringify(params || {})}`
  }
  
  /**
   * 设置缓存
   */
  static set(url: string, params: any, data: any, ttl = 5 * 60 * 1000): void {
    const key = this.generateKey(url, params)
    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      ttl
    })
  }
  
  /**
   * 获取缓存
   */
  static get(url: string, params?: any): any | null {
    const key = this.generateKey(url, params)
    const cached = this.cache.get(key)
    
    if (!cached) {
      return null
    }
    
    const { data, timestamp, ttl } = cached
    
    if (Date.now() - timestamp > ttl) {
      this.cache.delete(key)
      return null
    }
    
    return data
  }
  
  /**
   * 删除缓存
   */
  static delete(url: string, params?: any): void {
    const key = this.generateKey(url, params)
    this.cache.delete(key)
  }
  
  /**
   * 清空缓存
   */
  static clear(): void {
    this.cache.clear()
  }
}

// 带缓存的GET请求
Request.getCached = function<T = any>(
  url: string,
  params?: any,
  config?: RequestConfig & { cache?: boolean; cacheTTL?: number }
): Promise<ApiResponse<T>> {
  const { cache = false, cacheTTL = 5 * 60 * 1000, ...requestConfig } = config || {}
  
  if (cache) {
    const cached = RequestCache.get(url, params)
    if (cached) {
      return Promise.resolve(cached)
    }
  }
  
  return Request.get<T>(url, params, requestConfig).then((response) => {
    if (cache) {
      RequestCache.set(url, params, response, cacheTTL)
    }
    return response
  })
}

// 请求拦截器管理
class InterceptorManager {
  /**
   * 添加请求拦截器
   */
  static addRequestInterceptor(
    onFulfilled?: (config: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig>,
    onRejected?: (error: any) => any
  ): number {
    return service.interceptors.request.use(onFulfilled, onRejected)
  }
  
  /**
   * 添加响应拦截器
   */
  static addResponseInterceptor(
    onFulfilled?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>,
    onRejected?: (error: any) => any
  ): number {
    return service.interceptors.response.use(onFulfilled, onRejected)
  }
  
  /**
   * 移除请求拦截器
   */
  static removeRequestInterceptor(id: number): void {
    service.interceptors.request.eject(id)
  }
  
  /**
   * 移除响应拦截器
   */
  static removeResponseInterceptor(id: number): void {
    service.interceptors.response.eject(id)
  }
}

// 导出
export default Request
export { service, RequestCache, InterceptorManager }
export type { RequestConfig }